 #include <QtGui>
 #include "edge.h"
 #include <math.h>
#include "scene.h"
#include <iostream>

 const qreal Pi = 3.14;

 Edge::Edge(DiagramItem *startItem, DiagramItem *endItem, EdgeType edgeType,
          QGraphicsItem *parent, QGraphicsScene *scene)
     : QGraphicsPathItem(parent, scene)
 {
     myStartItem = startItem;
     myEndItem = endItem;
	 myEdgeType = edgeType;
	 isComplex = false; intrans = false; startUp = 0 ; endUp = false;
	 //per = 0;
	 branchRight = false;
	 branchLeft = false;
	 
     setFlag(QGraphicsItem::ItemIsSelectable, true);
     myColor = Qt::black;
     setPen(QPen(myColor, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
     myId = "e" + QString::number(rand());
 }

  void Edge::addEdge(Edge *arrow)
 {
     conEdges.push_back(arrow);
 }

QColor Edge::Color( ) const
{
	return myColor;
}

void Edge::setColor(QColor c) 
{
	if ( myColor != Qt::lightGray )
		myOldColor = myColor;
	myColor = c;
	update();
} 
void Edge::setOldColor() 
{
	myColor = myOldColor;
	update();
} 

 QPainterPath Edge::shape() const
 {
     QPainterPath path ;
	 if (myEdgeType != transcription )
	 {
		 for (int i = 0; i < points.size()-1; i++)
			 path.addRect(QRectF(points.at(i) + QPointF(2,2), points.at(i+1) - QPointF(2,2)));
	 } else
	 {
		 int i ;
		 for (i = 0; i < points.size()-2; i++)
			 path.addRect(QRectF(points.at(i) + QPointF(2,2), points.at(i+1) - QPointF(2,2)));
		 path.addRect(QRectF(points.at(i) + QPointF(-8,2), points.at(i+1) - QPointF(10,-20)));
	 }


	 QPainter p;
	 p.setPen(QPen(QColor(79, 106, 25), 1, Qt::SolidLine,
                     Qt::FlatCap, Qt::MiterJoin));

	 p.drawPath(path);
     return path;
 }
void Edge::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{

	QGraphicsItem::mousePressEvent(mouseEvent);
	
}
void Edge::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{

    for ( int i = 1 ; i < points.size()-2 ; i++)
    {
        if ( points.at(i).x() == points.at(i+1).x() &&  points.at(i).x()-50 < mouseEvent->scenePos().x() &&  mouseEvent->scenePos().x() < points.at(i).x()+50
        && points.at(i) != points.at(i+1) && ( (points.at(i).y() < points.at(i+1).y() && points.at(i).y() < mouseEvent->scenePos().y()  && mouseEvent->scenePos().y() < points.at(i+1).y())
        || (points.at(i).y() > points.at(i+1).y() && points.at(i).y() > mouseEvent->scenePos().y()  && mouseEvent->scenePos().y() > points.at(i+1).y()) ) )
        {
            qreal y = points.at(i).y();
            qreal y1 = points.at(i+1).y();
            points.replace(i, QPointF(mouseEvent->scenePos().x(), y )) ;
            points.replace(i+1, QPointF(mouseEvent->scenePos().x(), y1 )) ;
            break;

        } else if( (points.at(i).y() == points.at(i+1).y()) &&  points.at(i).y()-50 < mouseEvent->scenePos().y()  && mouseEvent->scenePos().y() < points.at(i).y()+50
        && points.at(i) != points.at(i+1) && ( (points.at(i).x() < points.at(i+1).x() && points.at(i).x() < mouseEvent->scenePos().x()  && mouseEvent->scenePos().x() < points.at(i+1).x())
        || (points.at(i).x() > points.at(i+1).x() && points.at(i).x() > mouseEvent->scenePos().x()  && mouseEvent->scenePos().x() > points.at(i+1).x()) )  )
        {
            qreal x = points.at(i).x();
            qreal x1 = points.at(i+1).x();
            points.replace(i, QPointF(x, mouseEvent->scenePos().y() )) ;
            points.replace(i+1, QPointF(x1, mouseEvent->scenePos().y() )) ;
            break;
        }
    }
    change();
    update();

}
void Edge::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
	QGraphicsItem::mouseReleaseEvent(mouseEvent);
}
/*void Edge::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)   // for next version
{
	QString text;
    text = QInputDialog::getText(event->widget(),"Edit Text", "Enter new text:",QLineEdit::Normal, name);
    if ( text!= "")
       name = text;
	
}*/
void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
           QWidget *)
{
	//if (myStartItem->collidesWithItem(myEndItem)  )
     //    return;
	
	QPen myPen = pen();
	myPen.setColor(myColor);
	qreal arrowSize = 10;
	painter->setPen(myPen);
	painter->setBrush(Qt::NoBrush);
	
	if ( myEdgeType == Edge::nonCovalent )
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		QLineF centerLine(points.at(points.size()-2), points.last());
		QLineF centerLine2(points.at(1), points.first());
		intersectStartItem();
		intersect();
		double angle = ::acos(-centerLine.dx() / centerLine.length());

		if (-centerLine.dy() >= 0)
			angle = (Pi * 2) - angle; 

		double angle2 = ::acos(-centerLine2.dx() / centerLine2.length());

		if (-centerLine2.dy() >= 0)
			angle2 = (Pi * 2) - angle2; 

		QPointF arrowP1 = points.last() + QPointF(sin(angle + Pi / 3) * arrowSize,
                                         cos(angle + Pi / 3) * arrowSize);
		QPointF arrowP2 = points.last() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                         cos(angle + Pi - Pi / 3) * arrowSize);
		QPointF arrowP3 = points.first() + QPointF(sin(angle2 + Pi / 3) * arrowSize,
                                         cos(angle2 + Pi / 3) * arrowSize);
		QPointF arrowP4 = points.first() + QPointF( sin(angle2 + Pi - Pi / 3) * arrowSize,
										 cos(angle2 + Pi - Pi / 3) * arrowSize );

		arrowHead.clear();
		arrowHead2.clear();

		QPointF p2 = QPointF(points.last().x() + 2, points.last().y());
		QPointF p4 = QPointF(points.first().x() , points.first().y() + 2);
		arrowHead << points.last() << arrowP1 << p2 <<  arrowP2;
		arrowHead2 << points.first() << arrowP3 << p4 <<  arrowP4;
				QPainterPath path(points.first());

		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);
		painter->drawPolygon(arrowHead);
		painter->drawPolygon(arrowHead2);



	}else if ( myEdgeType == Edge::covalentMo )
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		QLineF centerLine(points.at(points.size()-2), points.last());
		double angle = ::acos(-centerLine.dx() / centerLine.length());
		intersect();
		intersectStartItem();
		if (-centerLine.dy() >= 0)
			angle = (Pi * 2) - angle; 

		QPointF arrowP1 = points.last() + QPointF(sin(angle + Pi / 3) * arrowSize,
                                         cos(angle + Pi / 3) * arrowSize);
		QPointF arrowP2 = points.last() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                         cos(angle + Pi - Pi / 3) * arrowSize);

		arrowHead.clear();
		QPointF p2 = QPointF(points.last().x() + 2, points.last().y());
		arrowHead << points.last() << arrowP1 << p2 << arrowP2;
		QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);
		painter->setBrush(Qt::black);
		painter->drawPolygon(arrowHead);

	} 
	else if ( myEdgeType ==  covalentBond)
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		intersect();
		intersectStartItem();
		QPainterPath path;

		if ( points.first().y() < points.at(1).y() )
		{
			path.addRect(QRectF(QPointF(points.first().x()-5, points.first().y()), QPointF(points.first().x()+5, points.first().y() +10)));
			path.moveTo(QPointF(points.first().x(), points.first().y() + 10));

		} else if ( points.first().y() > points.at(1).y() )
		{
			path.addRect(QRectF(QPointF(points.first().x()-5, points.first().y()-10), QPointF(points.first().x()+5, points.first().y() )));
			path.moveTo(QPointF(points.first().x(), points.first().y() - 10));

		} else if ( points.first().x() < points.at(1).x())
		{
			path.addRect(QRectF(QPointF(points.first().x(), points.first().y()-5), QPointF(points.first().x()+10, points.first().y() +5)));
			path.moveTo(QPointF(points.first().x() + 10, points.first().y()));

		} else
		{
			path.addRect(QRectF(QPointF(points.first().x()-10, points.first().y()-5), QPointF(points.first().x(), points.first().y() +5)));
			path.moveTo(QPointF(points.first().x() - 10 , points.first().y()));
		}
		for ( int i = 1 ; i < points.size()-1; i++)
		{
			path.lineTo(points.at(i));
		}
		if ( points.last().y() < points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() + 10));
			path.addRect(QRectF(QPointF(points.last().x()-5, points.last().y()), QPointF(points.last().x()+5, points.last().y() +10)));

		} else if ( points.last().y() > points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() - 10));
			path.addRect(QRectF(QPointF(points.last().x()-5, points.last().y()-10), QPointF(points.last().x()+5, points.last().y() )));

		} else if ( points.last().x() < points.at(points.count()-2).x())
		{
			path.lineTo(QPointF(points.last().x() + 10, points.last().y()));
			path.addRect(QRectF(QPointF(points.last().x(), points.last().y()-5), QPointF(points.last().x()+10, points.last().y() +5)));
		
		} else
		{
			path.lineTo(QPointF(points.last().x() - 10 , points.last().y()));
			path.addRect(QRectF(QPointF(points.last().x()-10, points.last().y()-5), QPointF(points.last().x(), points.last().y() +5)));
		}
		setPath(path);
		painter->drawPath(path);

	}
	else if ( myEdgeType == Edge::stoichiometric )
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		QLineF centerLine(points.at(points.size()-2), points.last());
		double angle = ::acos(-centerLine.dx() / centerLine.length());
		intersect();
		intersectStartItem();
		if (-centerLine.dy() >= 0)
			angle = (Pi * 2) - angle; 

		QPointF arrowP1 = points.last() + QPointF(sin(angle + Pi / 3) * arrowSize,
                                         cos(angle + Pi / 3) * arrowSize);
		QPointF arrowP2 = points.last() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                         cos(angle + Pi - Pi / 3) * arrowSize);

		arrowHead.clear();
		arrowHead << points.last() << arrowP1 << arrowP2;
		QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);
		painter->setBrush(myColor);
		painter->drawPolygon(arrowHead);


	}
	else if ( myEdgeType == lossReactant )
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		QLineF centerLine(points.at(points.size()-2), points.last());
		double angle = ::acos(-centerLine.dx() / centerLine.length());
		intersect();
		intersectStartItem();
		if (-centerLine.dy() >= 0)
			angle = (Pi * 2) - angle; 

		QPointF arrowP1 = points.last() + QPointF(sin(angle + Pi / 3) * arrowSize,
                                         cos(angle + Pi / 3) * arrowSize);
		QPointF arrowP2 = points.last() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                         cos(angle + Pi - Pi / 3) * arrowSize);

		arrowHead.clear();
		arrowHead << points.last() << arrowP1 << arrowP2;
		QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);
		painter->setBrush(Qt::white);
		painter->drawPolygon(arrowHead);

	}
	else if ( myEdgeType == transcription)
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));

		QLineF centerLine(points.at(points.size()-2), points.last());
		double angle = ::acos(-centerLine.dx() / centerLine.length());
		intersect();
		intersectStartItem();
		if (-centerLine.dy() >= 0)
			angle = (Pi * 2) - angle; 

		QPointF arrowP1 = points.last()+ QPointF(sin(angle + Pi / 3) * arrowSize,
                                         cos(angle + Pi / 3) * arrowSize);
		QPointF arrowP2 = points.last() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                         cos(angle + Pi - Pi / 3) * arrowSize);

		arrowHead.clear();
		arrowHead << points.last() << arrowP1 << arrowP2;
		QPainterPath path(points.first());
		
		
		int i;
		for ( i = 1 ; i < points.size()-2; i++)
		{
			path.lineTo(points.at(i));
		}
		if ( points.last().y() < points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x() - 10 , points.at(i).y()));
			path.lineTo(QPointF(points.last().x() - 10 , points.last().y()+20));
			path.lineTo(QPointF(points.last().x() , points.last().y()+ 20));
			path.lineTo(QPointF(points.last().x() , points.last().y()));

		} else if ( points.last().y() > points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x() - 10 , points.at(i).y()));
			path.lineTo(QPointF(points.last().x() - 10, points.last().y()-20));
			path.lineTo(QPointF(points.last().x() , points.last().y()- 20));
			path.lineTo(QPointF(points.last().x() , points.last().y()));

		} else if ( points.last().x() < points.at(points.count()-2).x())
		{
			path.lineTo(QPointF(points.at(i).x(), points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()+ 20, points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()+ 20, points.last().y()));
			path.lineTo(QPointF(points.last().x(), points.last().y()));
		
		} else
		{
			path.lineTo(QPointF(points.at(i).x(), points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()- 20, points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()- 20, points.last().y()));
			path.lineTo(QPointF(points.last().x(), points.last().y()));
		}
		setPath(path);
		
		painter->drawPath(path);
		painter->setBrush(Qt::white);
		painter->drawPolygon(arrowHead);

	}else if (myEdgeType == combination )
	{

		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));

		intersect();
		intersectStartItem();

		QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);
		painter->setBrush(Qt::black);

	}else if ( myEdgeType ==  firstFeature)
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		intersect();
		intersectStartItem();
		QPainterPath path;

		if ( points.first().y() < points.at(1).y() )
		{
			path.addRect(QRectF(QPointF(points.first().x()-5, points.first().y()), QPointF(points.first().x()+5, points.first().y() +10)));
			path.moveTo(QPointF(points.first().x(), points.first().y() + 10));

		} else if ( points.first().y() > points.at(1).y() )
		{
			path.addRect(QRectF(QPointF(points.first().x()-5, points.first().y()-10), QPointF(points.first().x()+5, points.first().y() )));
			path.moveTo(QPointF(points.first().x(), points.first().y() - 10));

		} else if ( points.first().x() < points.at(1).x())
		{
			path.addRect(QRectF(QPointF(points.first().x(), points.first().y()-5), QPointF(points.first().x()+10, points.first().y() +5)));
			path.moveTo(QPointF(points.first().x() + 10, points.first().y()));

		} else
		{
			path.addRect(QRectF(QPointF(points.first().x()-10, points.first().y()-5), QPointF(points.first().x(), points.first().y() +5)));
			path.moveTo(QPointF(points.first().x() - 10 , points.first().y()));
		}
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);

	}else if (myEdgeType == nextFeature )
	{

		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));

		intersect();
		intersectStartItem();

		QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);
		painter->setBrush(Qt::black);

	}	else if ( myEdgeType == cleavage )
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		//intersect();
		intersectStartItem();
		QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size()- 1; i++)
		{
			path.lineTo(points.at(i));
		}
		if ( points.last().x() > points.at(points.count()-2).x() )
		{
			path.lineTo(QPointF(points.last().x()- 10, points.last().y()));
                        path.lineTo(QPointF(points.last().x()- 10, points.last().y()+10));
                        path.lineTo(QPointF(points.last().x()+ 10, points.last().y() -5));


		} else if ( points.last().y() > points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y()- 10));
                        path.lineTo(QPointF(points.last().x()- 10, points.last().y()-10));
                        path.lineTo(QPointF(points.last().x()+ 5, points.last().y()+ 10));

		} else if ( points.last().x() < points.at(points.count()-2).x())
		{
			path.lineTo(QPointF(points.last().x()+ 10, points.last().y()));
                        path.lineTo(QPointF(points.last().x()+ 10, points.last().y()+ 10));
                        path.lineTo(QPointF(points.last().x()- 10, points.last().y() - 5));
		
		} else if ( points.last().y() < points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() + 10));
                        path.lineTo(QPointF(points.last().x() +10, points.last().y()+10));
                        path.lineTo(QPointF(points.last().x()-5, points.last().y()- 10));

		}
		setPath(path);
		painter->drawPath(path);

	}else if ( myEdgeType == stimulation)
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		intersectStartItem();
		QPainterPath path(points.first());
		if ( branchRight )
		{
			if ( (points.at(1).y() - points.first().y())  > 1 )
			{
				path.moveTo(points.first().x()+ 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if (( points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() - 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ((points.at(1).x()- points.first().x()) > 1 )
			{
				path.moveTo(points.first().x() , points.first().y() - 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() + 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		if ( branchLeft )
		{
			if ( (points.at(1).y() - points.first().y()) > 1  )
			{
				path.moveTo(points.first().x()- 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if ( (points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() + 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ( (points.at(1).x() - points.first().x()) > 1)
			{
				path.moveTo(points.first().x() , points.first().y() + 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() - 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		painter->drawPath(path);
		QLineF centerLine(points.at(points.size()-2), points.last());

		double angle = ::acos(-centerLine.dx() / centerLine.length());

		if (-centerLine.dy() >= 0)
			angle = (Pi * 2) - angle; 

		QPointF arrowP1 = points.last() + QPointF(sin(angle + Pi / 3) * arrowSize,
                                         cos(angle + Pi / 3) * arrowSize);
		QPointF arrowP2 = points.last() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                         cos(angle + Pi - Pi / 3) * arrowSize);

		arrowHead.clear();
		arrowHead << points.last()<< arrowP1 << arrowP2;
		painter->setBrush(Qt::white);
		painter->drawPolygon(arrowHead);
	}
	else if ( myEdgeType == requirement)
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		intersectStartItem();
		QPainterPath path(points.first());
		if ( branchRight )
		{
			if ( (points.at(1).y() - points.first().y())  > 1 )
			{
				path.moveTo(points.first().x()+ 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if (( points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() - 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ((points.at(1).x()- points.first().x()) > 1 )
			{
				path.moveTo(points.first().x() , points.first().y() - 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() + 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		if ( branchLeft )
		{
			if ( (points.at(1).y() - points.first().y()) > 1  )
			{
				path.moveTo(points.first().x()- 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if ( (points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() + 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ( (points.at(1).x() - points.first().x()) > 1)
			{
				path.moveTo(points.first().x() , points.first().y() + 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() - 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		if ( points.last().y() < points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() + arrowSize + 4));
			path.lineTo(QPointF(points.last().x()- arrowSize, points.last().y() + arrowSize + 4));
			path.lineTo(QPointF(points.last().x()+ arrowSize, points.last().y() + arrowSize + 4));

		} else if ( points.last().y() > points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() - arrowSize - 4));
			path.lineTo(QPointF(points.last().x()- arrowSize, points.last().y() - arrowSize - 4));
			path.lineTo(QPointF(points.last().x()+ arrowSize, points.last().y() - arrowSize - 4));

		} else if ( points.last().x() < points.at(points.count()-2).x())
		{
			path.lineTo(QPointF(points.last().x() + arrowSize + 4, points.last().y()));
			path.lineTo(QPointF(points.last().x() + arrowSize + 4, points.last().y() + arrowSize ));
			path.lineTo(QPointF(points.last().x() + arrowSize + 4, points.last().y() - arrowSize ));
		
		} else
		{
			path.lineTo(QPointF(points.last().x() - arrowSize - 4, points.last().y()));
			path.lineTo(QPointF(points.last().x() - arrowSize - 4, points.last().y() + arrowSize ));
			path.lineTo(QPointF(points.last().x() - arrowSize - 4, points.last().y() - arrowSize ));
		}
		setPath(path);
		painter->drawPath(path);
		QLineF centerLine(points.at(points.size()-2), points.last());

		double angle = ::acos(-centerLine.dx() / centerLine.length());

		if (-centerLine.dy() >= 0)
			angle = (Pi * 2) - angle; 

		QPointF arrowP1 = points.last() + QPointF(sin(angle + Pi / 3) * arrowSize,
                                         cos(angle + Pi / 3) * arrowSize);
		QPointF arrowP2 = points.last() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                         cos(angle + Pi - Pi / 3) * arrowSize);

		arrowHead.clear();
		arrowHead << points.last()<< arrowP1 << arrowP2;
		painter->setBrush(Qt::white);
		painter->drawPolygon(arrowHead);
	}
	else if ( myEdgeType == inhibition)
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		intersectStartItem();
		QPainterPath path(points.first());
		if ( branchRight )
		{
			if ( (points.at(1).y() - points.first().y())  > 1 )
			{
				path.moveTo(points.first().x()+ 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if (( points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() - 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ((points.at(1).x()- points.first().x()) > 1 )
			{
				path.moveTo(points.first().x() , points.first().y() - 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() + 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		if ( branchLeft )
		{
			if ( (points.at(1).y() - points.first().y()) > 1  )
			{
				path.moveTo(points.first().x()- 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if ( (points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() + 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ( (points.at(1).x() - points.first().x()) > 1)
			{
				path.moveTo(points.first().x() , points.first().y() + 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() - 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		for ( int i = 1 ; i < points.size()-1; i++)
		{
			path.lineTo(points.at(i));
		}
		if ( points.last().y() < points.at(points.count()-2).y()-0.05 )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() + arrowSize + 4));
			path.lineTo(QPointF(points.last().x()- arrowSize, points.last().y() + arrowSize + 4));
			path.lineTo(QPointF(points.last().x()+ arrowSize, points.last().y() + arrowSize + 4));

		} else if ( points.last().y() > points.at(points.count()-2).y()+0.05 )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() - arrowSize - 4));
			path.lineTo(QPointF(points.last().x()- arrowSize, points.last().y() - arrowSize - 4));
			path.lineTo(QPointF(points.last().x()+ arrowSize, points.last().y() - arrowSize - 4));

		} else if ( points.last().x() < points.at(points.count()-2).x()-0.05)
		{
			path.lineTo(QPointF(points.last().x() + arrowSize + 4, points.last().y()));
			path.lineTo(QPointF(points.last().x() + arrowSize + 4, points.last().y() + arrowSize ));
			path.lineTo(QPointF(points.last().x() + arrowSize + 4, points.last().y() - arrowSize ));
		
		} else
		{
			path.lineTo(QPointF(points.last().x() - arrowSize - 4, points.last().y()));
			path.lineTo(QPointF(points.last().x() - arrowSize - 4, points.last().y() + arrowSize ));
			path.lineTo(QPointF(points.last().x() - arrowSize - 4, points.last().y() - arrowSize ));
		}
		setPath(path);
		//points.pop_back();
		painter->drawPath(path);
	
			}
	 else if ( myEdgeType == catalysis)
	{
		if (isSelected()) 
			painter->setPen(QPen(myColor, 1, Qt::DashLine));
		intersectStartItem();
		QPainterPath path(points.first());
		if ( branchRight )
		{
			if ( (points.at(1).y() - points.first().y())  > 1 )
			{
				path.moveTo(points.first().x()+ 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if (( points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() - 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ((points.at(1).x()- points.first().x()) > 1 )
			{
				path.moveTo(points.first().x() , points.first().y() - 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() + 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		if ( branchLeft )
		{
			if ( (points.at(1).y() - points.first().y()) > 1  )
			{
				path.moveTo(points.first().x()- 10, points.first().y() );
				path.lineTo(points.first().x() , points.first().y() + 10);

			} else if ( (points.first().y() - points.at(1).y()) > 1 )
			{
				path.moveTo(points.first().x() + 10 , points.first().y() );
				path.lineTo(points.first().x() , points.first().y() - 10);

			} else if ( (points.at(1).x() - points.first().x()) > 1)
			{
				path.moveTo(points.first().x() , points.first().y() + 10 );
				path.lineTo(points.first().x() + 10, points.first().y());
			
			} else
			{
				path.moveTo( points.first().x() , points.first().y() - 10);
				path.lineTo( points.first().x() - 10 , points.first().y() );
			}
		}
		for ( int i = 1 ; i < points.size()-1; i++)
		{
			path.lineTo(points.at(i));
		}
		if ( points.last().y() < points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() + arrowSize ));
			path.addEllipse(QPointF(points.last().x(), points.last().y()+ arrowSize  - arrowSize/2), arrowSize/2, arrowSize/2);

		} else if ( points.last().y() > points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x(), points.last().y() - arrowSize ));
			path.addEllipse(QPointF(points.last().x(), points.last().y()- arrowSize  + arrowSize/2), arrowSize/2, arrowSize/2);

		} else if ( points.last().x() < points.at(points.count()-2).x())
		{
			path.lineTo(QPointF(points.last().x() + arrowSize , points.last().y()));
			path.addEllipse(QPointF(points.last().x() + arrowSize  - arrowSize/2, points.last().y()), arrowSize/2, arrowSize/2);
		
		} else
		{
			path.lineTo(QPointF(points.last().x() - arrowSize , points.last().y()));
			path.addEllipse(QPointF(points.last().x() - arrowSize  + arrowSize/2, points.last().y()), arrowSize/2, arrowSize/2);
		}
		//path.addEllipse(QPointF(points.last().x() - arrowSize * 2 + arrowSize/2, points.last().y()), arrowSize/2, arrowSize/2);
		setPath(path);
		painter->drawPath(path);
	}

		
}
QPointF Edge::intersectStartItem()
{
	QLineF centerLine(points.at(1), points.first());
	qreal len = centerLine.length();
	centerLine.setLength(len* 20);  // used when name of the species is shortened
	QPolygonF startPolygon;
	startPolygon = myStartItem->polygon();
	QPointF p1 = startPolygon.first() + myStartItem->pos();
	QPointF p2,p3;
	QPointF intersectionPoint;
	QLineF polyLine;
	int distanceF = 100000;
	int counter = 0;
	for (int i = 1; i < startPolygon.count(); ++i) 
	{
		p2 = startPolygon.at(i) + myStartItem->pos();
		polyLine = QLineF(p1, p2);
		QLineF::IntersectType intersectType =
		polyLine.intersect(centerLine, &intersectionPoint);
		if (intersectType == QLineF::BoundedIntersection && (distance(intersectionPoint,points.at(1)) < distanceF))
		{
			distanceF = distance(intersectionPoint,points.at(1));
			p3 = intersectionPoint;
			counter++;
			if ( startUp == 0)
			{
				if ( p1.y() == p2.y() )
					startUp = 1;
				else
					startUp = 2;
			}
		}
		p1 = p2;
	}
	if (counter == 0)
		return points.first();

	points.first() = p3;

	if ( myStartItem->diagramType() == DiagramItem::DiagramType(8) )
		points.first() = myStartItem->pos();

	return p3;

}
QPointF Edge::intersect()
{

		QLineF centerLine(points.at(points.size()-2), points.last());
		qreal len = centerLine.length();
		centerLine.setLength(len* 20); // used when name of the species is shortened
		QPolygonF endPolygon = myEndItem->polygon();
		QPointF p1 = endPolygon.first() + myEndItem->pos();
		QPointF p2, p3;
		QPointF intersectionPoint;
		QLineF polyLine;
		int distanceF = 100000;
		int counter = 0;
		for (int i = 1; i < endPolygon.count(); ++i) 
		{
			p2 = endPolygon.at(i) + myEndItem->pos();
			polyLine = QLineF(p1, p2);
			QLineF::IntersectType intersectType =
			polyLine.intersect(centerLine, &intersectionPoint);
			if (intersectType == QLineF::BoundedIntersection && (distance(intersectionPoint,points.at(points.size()-2)) < distanceF))
			{
				distanceF = distance(intersectionPoint,points.at(points.size()-2));
				p3 = intersectionPoint;
				counter++;
                                if ( p1.y() == p2.y() )
                                        endUp = true;
                                else
                                        endUp = false;
			}
			p1 = p2;
		}
		if (counter == 0)
		{
			if ( (points.last().y() < points.at(points.size()-2).y()+0.005) &&  (points.last().y() > points.at(points.size()-2).y()-0.005))
				endUp = false;
			else
				endUp = true;
            return points.last();
		}
		if ( myEdgeType < 9 )
			points.last() = p3 ;
		else return points.last();
				

        return p3;

}
QVector<QPointF> Edge::trackDiagramItem()
{

	QPointF py, px;
		if ( !myStartItem->edges.contains(this))
		{
			py = intersectStartItem();
			myStartItem->addEdge(this);
			startx = py.x() - myStartItem->scenePos().x();
			starty = py.y() - myStartItem->scenePos().y();
		}
		if ( !myEndItem->edges.contains(this))
		{
			px = intersect();
			myEndItem->addEdge(this);
			endx = px.x() - myEndItem->scenePos().x();
			endy = px.y() - myEndItem->scenePos().y();
		}


	if ( points.size() > 3 )
	{
		bool c = endUp;
		int c2 = startUp;

		points.pop_back();
		points.pop_front();

		QPointF p = QPointF(myEndItem->scenePos().x()+endx,myEndItem->scenePos().y()+endy) ;
		QPointF p2 = QPointF(points.at(points.size()-2).x(),p.y());
		QPointF p3 = QPointF(myStartItem->scenePos().x()+startx,myStartItem->scenePos().y()+starty) ;
		QPointF p4 = QPointF(p.x(), points.at(points.size()-2).y());
		QPointF p5 = QPointF(points.at(1).x(),p3.y());
		QPointF p6 = QPointF(p3.x(), points.at(1).y());

		points.pop_back();
		points.pop_front();

		if ( !c )
		{
			points.push_back(p2);
			points.push_back(p);
		} else
		{
			points.push_back(p4);
			points.push_back(p);
		}
		if ( startUp == 2 )
		{
			points.push_front(p5);
			points.push_front(p3);
		} else
		{
			points.push_front(p6);
			points.push_front(p3);
		}
    	QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);
		update();
	} else if ( points.size() == 3 )
	{

		int c = startUp;
		points.clear();

		if( startUp == 1)
		{
			points.insert(0,QPointF(myStartItem->scenePos().x()+startx,myStartItem->scenePos().y()+starty)) ;
			points.insert(1,QPointF(myStartItem->scenePos().x()+startx, myEndItem->scenePos().y()+endy));
			points.insert(2,QPointF(myEndItem->scenePos().x()+endx,myEndItem->scenePos().y()+endy));
		}
		else
		{
			points.insert(0,QPointF(myStartItem->scenePos().x()+startx,myStartItem->scenePos().y()+starty));
			points.insert(1,QPointF(myEndItem->scenePos().x()+endx, myStartItem->scenePos().y()+starty));
			points.insert(2,QPointF(myEndItem->scenePos().x()+endx,myEndItem->scenePos().y()+endy));
		}
    	QPainterPath path(points.first());
		for ( int i = 1 ; i < points.size(); i++)
		{
			path.lineTo(points.at(i));
		}
		setPath(path);	
		if ( myEdgeType == 5) // because qt does not update before setting anchor pos
		{		QPainterPath path(points.first());
		
		int i;
		for ( i = 1 ; i < points.size()-2; i++)
		{
			path.lineTo(points.at(i));
		}
		if ( points.last().y() < points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x() - 10 , points.at(i).y()));
			path.lineTo(QPointF(points.last().x() - 10 , points.last().y()+20));
			path.lineTo(QPointF(points.last().x() , points.last().y()+ 20));
			path.lineTo(QPointF(points.last().x() , points.last().y()));

		} else if ( points.last().y() > points.at(points.count()-2).y() )
		{
			path.lineTo(QPointF(points.last().x() - 10 , points.at(i).y()));
			path.lineTo(QPointF(points.last().x() - 10, points.last().y()-20));
			path.lineTo(QPointF(points.last().x() , points.last().y()- 20));
			path.lineTo(QPointF(points.last().x() , points.last().y()));

		} else if ( points.last().x() < points.at(points.count()-2).x())
		{
			path.lineTo(QPointF(points.at(i).x(), points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()+ 20, points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()+ 20, points.last().y()));
			path.lineTo(QPointF(points.last().x(), points.last().y()));
		
		} else
		{
			path.lineTo(QPointF(points.at(i).x(), points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()- 20, points.last().y() + 10));
			path.lineTo(QPointF(points.last().x()- 20, points.last().y()));
			path.lineTo(QPointF(points.last().x(), points.last().y()));
		}
		setPath(path);
		}
		update();
	} else if (  points.size() < 3 )
	{
		if ( points.at(1).x()-0.05 <= points.first().x() && points.first().x() <= points.at(1).x()+0.05)
		{
			points.insert(1,QPointF(points.at(0).x(),(points.at(0).y()+points.last().y())/2));
			points.insert(2,QPointF(points.last().x(),(points.at(0).y()+points.last().y())/2));
		} else
		{
			points.insert(1,QPointF((points.at(0).x()+points.last().x())/2, points.at(0).y()));
			points.insert(2,QPointF((points.at(0).x()+points.last().x())/2, points.last().y()));
		}

		QPainterPath path(points.first());
		path.lineTo(points.at(1));
		path.lineTo(points.at(2));
		path.lineTo(points.at(3));
		setPath(path);
		update();

	}


	return points;

}


bool Edge::containPoint (const QLineF &line,const QPointF &p )
{
	QPointF intersectionPoint;
	QLineF line2 = QLineF(QPointF(p.x()-3, p.y()-3),QPointF(p.x()+3, p.y()+3) );
			QLineF::IntersectType intersectType =
			line.intersect(line2, &intersectionPoint);
			if (intersectType == QLineF::BoundedIntersection)
				return true;
			else return false;

}

void Edge::change()
{

				trackDiagramItem();
			
				if (isComplex)
				{
					//complex->pa = trackDiagramItem();
					complex->setPos(QPointF(complex->host->path().pointAtPercent(complex->per)));
				}
				if (intrans)
				{
					//trans->pa = trackDiagramItem();
					trans->setPos(QPointF(trans->host->path().pointAtPercent(trans->per)));
				}
				if (!invisibleItems.isEmpty())
				{
					foreach (DiagramItem* item, invisibleItems)
						item->setPos(QPointF(item->host->path().pointAtPercent(item->per)));
				}

			if ( !conEdges.empty() )
			{
				foreach (Edge* edged, conEdges) 
					edged->change();
			}

}
int Edge::distance(const QPointF &p1,const QPointF &p2)
{
        float diffX = float(pow(p1.x() - p2.x(),2));
        float diffY = float(pow(p1.y() - p2.y(),2));
        return int(sqrt(diffX + diffY));
}
void Edge::reverse()
{
	DiagramItem *item = myEndItem;
	myEndItem = myStartItem;
	myStartItem = item;
	QVector <QPointF> p = points;
	int j = points.size();
	points.clear();
	for (int i = 0; i < j ; i++)
	{
		points.append(p.at(j-i-1));
	}
	update();
	change();
}
QString Edge::returnEnumFirst(const int &num)
{
	if ( num == 0 )
		return "NonCovalentReversibleBinding";
	else if ( num == 1 )
		return "Line";
	else if ( num == 2 )
		return "CovalentIrreversibleBinding";
	else if ( num == 3 )
		return "Line";
	else if ( num == 4 )
		return "Line";
	else if ( num == 5 )
		return "Line";
	else if ( num == 6 )
		return "StateCombination";
	else if ( num == 7 )
        return "FirstFeature";
	else if ( num == 8 )
        return "NextFeature";
	else if ( num == 9 )
		return "Line";
	else if ( num > 9 &&  branchLeft  )
		return "BranchingLeft";
	else if ( num > 9 &&  branchRight  )
		return "BranchingRight";
	else
		return "Line";
}

QString Edge::returnEnumSecond(const int &num)
{
	if ( num == 0 )
		return "NonCovalentReversibleBinding";
	else if ( num == 1 )
		return "CovalentModification";
	else if ( num == 2 )
		return "CovalentIrreversibleBinding";
	else if ( num == 3 )
		return "StochiometricConversion";
	else if ( num == 4 )
		return "ProductionWithoutLoss";
	else if ( num == 5 )
		return "TemplateReaction";
	else if ( num == 6 )
		return "StateCombination";
	else if ( num == 7 )
		return "Line";
	else if ( num == 8 )
        return "NextFeature";
	else if ( num == 9 )
		return "CovalentBondCleavage";
	else if ( num == 10 )
		return "Stimulation";
	else if ( num == 11 )
		return "NecessaryStimulation";
	else if ( num == 12 )
		return "Inhibition";
    else
        return "Catalysis";
}



